<template>
  <Popup ref="popup" :placement="placement" :blur="blur" @mask-click="maskClick">
    <slot />
  </Popup>
</template>

<script lang="ts" setup>
import Popup from '@/components/popup/popup.vue';
import { ref, type PropType } from 'vue';
import { useLockFn, useNextTick } from '@/hooks';

const props = defineProps({
  maskClosable: {
    type: Boolean,
    default: true,
  },
  placement: {
    type: String as PropType<'top' | 'right' | 'bottom' | 'left' | 'center' | 'none'>,
    default: 'center'
  },
  blur: {
    type: Boolean,
    default: false,
  },
});

const emit = defineEmits(['maskClick']);

const popup = ref();
const show = ref(false);

const nextTick = useNextTick();

const open = useLockFn(async () => {
  if (show.value) return;
  // todo onMounted 并不能确定子组件被全部挂载，所以如果组件在 onMounted 调用 open 方法可能导致 popup.value 为 undefined 无法打开 modal 的情况
  // todo 解决办法是 $nextTick
  if (!popup.value) {
    await nextTick();
  }
  await popup.value?.open();
  await new Promise(resolve => setTimeout(resolve, 300));
  show.value = true;
});

const close = useLockFn(async () => {
  if (!show.value) return;
  await popup.value?.close();
  await new Promise(resolve => setTimeout(resolve, 300));
  show.value = false;
});

function maskClick(e: Event) {
  if (props.maskClosable) {
    close();
  }

  emit('maskClick', e);
}

defineExpose({ open, close });
</script>